gdk/x11: Transform XI_Motion based scroll into discrete
authorCarlos Garnacho <carlosg@gnome.org>
Wed, 16 Dec 2020 13:07:13 +0000 (14:07 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Wed, 16 Dec 2020 13:26:44 +0000 (14:26 +0100)
Depending on the input driver, we will get XI_Motion based scroll
events for regular mouse wheels. These are intended to be handled
as discrete scroll, so detect smooth scroll events that move by
exactly 1.0 in either direction.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3459
gdk/x11/gdkdevicemanager-xi2.c

index 8e6c05d15cfe07f7d34a765ada658119d1e63fe6..3165205a5f6631156660dca1549d85163c998283 100644 (file)
@@ -1716,19 +1716,49 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
             scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
                                       &xev->valuators, &delta_x, &delta_y))
           {
+            GdkModifierType state;
+
             GDK_DISPLAY_NOTE (display, EVENTS,
                      g_message ("smooth scroll: \n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f",
                                 xev->deviceid, xev->sourceid,
                                 xev->event, delta_x, delta_y));
 
-            event = gdk_scroll_event_new (surface,
-                                          device,
-                                          NULL,
-                                          xev->time,
-                                          _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
-                                          delta_x,
-                                          delta_y,
-                                          delta_x == 0.0 && delta_y == 0.0);
+            state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+
+            if (gdk_device_get_source (source_device) != GDK_SOURCE_TOUCHPAD &&
+                ((delta_x == 0.0 && ABS (delta_y) == 1.0) ||
+                 (ABS (delta_x) == 1.0 && delta_y == 0.0)))
+              {
+                GdkScrollDirection direction;
+
+                if (delta_x > 0)
+                  direction = GDK_SCROLL_RIGHT;
+                else if (delta_x < 0)
+                  direction = GDK_SCROLL_LEFT;
+                else if (delta_y > 0)
+                  direction = GDK_SCROLL_DOWN;
+                else
+                  direction = GDK_SCROLL_UP;
+
+                event = gdk_scroll_event_new_discrete (surface,
+                                                       device,
+                                                       NULL,
+                                                       xev->time,
+                                                       state,
+                                                       direction,
+                                                       FALSE);
+              }
+            else
+              {
+                event = gdk_scroll_event_new (surface,
+                                              device,
+                                              NULL,
+                                              xev->time,
+                                              state,
+                                              delta_x,
+                                              delta_y,
+                                              delta_x == 0.0 && delta_y == 0.0);
+              }
             break;
           }